﻿--[[
	Widget name	  	PropertySet
	Author     	 	Kurapica
--]]
     
-- PropertySet
do    
    local getmetatable = getmetatable
    local pairs = pairs
    local ipairs = ipairs
    local type = type
    local error = error
    local floor = floor
	local tostring = tostring
	local random = random
    local CreateFrame = IGAS.GUI.CreateFrame
    
	local _WidgetName = "PropertySet"
	local _Base = IGAS.GUI.Widget.Frame

    local _Widget = IGAS.Studio.Widget
    local _PropertyType = IGAS.GUI.Base.PropertyType
	
    ------------------------------------------------------
	---------------------   PropertySet   -------------------
	------------------------------------------------------
	local _WidgetName = "PropertySet"
    local _Base = "Frame"

    -- Scripts
	local _FrameBackdrop = {
        bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 16,
        insets = { left = 3, right = 3, top = 3, bottom = 3 }
	}
	
	local nodeHeight = 26
	local nodeIndent = 10
		
	local function SetProperty(obj, prop, value)
		obj[prop] = value
	end
	
	local function SetPropValue(self)
		local property
		local value
		
		if self.Parent.__Object and self.Parent.__Property then
			property = self.Parent.__Object:GetObjectType().Property[self.Parent.__Property]
			
			if property["Type"]["Type"] == "number" then
				-- If the property's type is number
				value = tonumber(self.Text)
				if not value then
					-- Need reset.
					self.Text = tostring(self.Parent.__Object[self.Parent.__Property])
					self:SetFocus()
				else
					if property["MinValue"] or property["MaxValue"] then
						-- Check the value whether if it's in the range
						if property["MinValue"] and value < property["MinValue"] then
							value = property["MinValue"]
						elseif property["MaxValue"] and value > property["MaxValue"] then
							value = property["MaxValue"]
						end
					end
					if self.Parent.__Object[self.Parent.__Property] == value then
						return
					end
					
					-- Set the property
					pcall(SetProperty, self.Parent.__Object, self.Parent.__Property, value)
					-- Refresh, maybe changed while setting a new value.
					self.Text = tostring(self.Parent.__Object[self.Parent.__Property])
					-- Fire OnPropertyChanged
					self.Parent:Fire("OnPropertyChanged", self.Parent.__Object, self.Parent.__Property, value)
				end
				
			elseif property["Type"]["Type"] == "string" then
				-- If the property's type is string
				value = tostring(self.Text)
				
				if self.Parent.__Object[self.Parent.__Property] == value then
					return
				end
				
				-- Set the property
				pcall(SetProperty, self.Parent.__Object, self.Parent.__Property, value)
				-- Refresh, maybe changed while setting a new value.
				self.Text = tostring(self.Parent.__Object[self.Parent.__Property])
				-- Fire OnPropertyChanged
				self.Parent:Fire("OnPropertyChanged", self.Parent.__Object, self.Parent.__Property, value)
				
			elseif property["Type"]["Type"] == "boolean" then
				-- If the property's type is boolean
				value = (self.Value and true) or false
				if self.Parent.__Object[self.Parent.__Property] == value then
					return
				end
				
				-- Set the property
				pcall(SetProperty, self.Parent.__Object, self.Parent.__Property, value)
				-- Refresh, maybe changed while setting a new value.
				self.Text = tostring((self.Parent.__Object[self.Parent.__Property] and true) or false)
				-- Fire OnPropertyChanged
				self.Parent:Fire("OnPropertyChanged", self.Parent.__Object, self.Parent.__Property, value)
				
			elseif property["Type"]["Type"] == "enum" then
				-- If the property's type is enum
				value = self.Text
				if self.Parent.__Object[self.Parent.__Property] == value then
					return
				end
				-- Set the property
				pcall(SetProperty, self.Parent.__Object, self.Parent.__Property, value)
				-- Refresh, maybe changed while setting a new value.
				self.Text = tostring(self.Parent.__Object[self.Parent.__Property])
				-- Fire OnPropertyChanged
				self.Parent:Fire("OnPropertyChanged", self.Parent.__Object, self.Parent.__Property, value)
			end
		end
	end
	
	local function GetPropValue(self)
		local property
		
		if self.Parent.__Object and self.Parent.__Property then
			property = self.Parent.__Object:GetObjectType().Property[self.Parent.__Property]
			
			if property["Type"]["Type"] == "number" then
				-- Refresh, maybe changed
				self.Text = tostring(self.Parent.__Object[self.Parent.__Property])
				
			elseif property["Type"]["Type"] == "string" then				
				-- Refresh, maybe changed
				self.Text = tostring(self.Parent.__Object[self.Parent.__Property])
				
			elseif property["Type"]["Type"] == "boolean" then
				-- Refresh, maybe changed
				self.Text = tostring((self.Parent.__Object[self.Parent.__Property] and true) or false)
				
			elseif property["Type"]["Type"] == "enum" then
				-- Refresh, maybe changed
				self.Text = tostring(self.Parent.__Object[self.Parent.__Property])
			end
		end
	end
	
	local function Set_OnValueChanged(self, value)
		SetPropValue(self)
	end
	
	local function Set_OnEnterPressed(self)
		local nextSet = self.Parent.Parent:GetChild("PropertySet"..(self.Parent.ID + 1))
		
		if nextSet and nextSet.Visible then
			nextSet.Set:SetFocus()
		end
	end
    
	local function Set_OnEditFocusGained(self)
		GetPropValue(self)
	end
	
	local function Set_OnEditFocusLost(self)
		SetPropValue(self)
	end
	
	-- ScriptType
	local _ScriptType = {
		["OnPropertyChanged"] = true,
	}
	    
	-- FuncProxy
	local _FuncProxy = {
		-- SetProperty
		["SetProperty"] = function (self, object, prop)
			local property
			
			if object and prop then
				self.__Object = object
				self.__Property = prop
				
				property = object:GetObjectType().Property[prop]
				self.Title.Text = prop
				if property["Type"]["Type"] == "number" or property["Type"]["Type"] == "string" then
					-- No need dropDown
					self.Set.DropdownBtn.Visible = false
					
					self.Set.Text = tostring(object[prop])
				else
					-- Show DropDownBtn
					self.Set.DropdownBtn.Visible = true
					
					if property["Type"]["Type"] == "boolean" then
						self.Set:SuspendLayout()
						self.Set:Clear()
						self.Set:AddItem(false, "false")
						self.Set:AddItem(true, "true")
						
						self.Set:ResumeLayout()
						
						self.Set.Text = tostring((object[prop] and true) or false)
					elseif property["Type"]["EnumType"] then
						self.Set:SetList(property["Type"]["EnumType"])
						
						self.Set.Text = tostring(object[prop])	
					end
				end
			else
				self.__Object = nil
				self.__Property = nil
				self.Title.Text = ""
				self.Set:Clear()
			end
		end,
    }
    
	-- Property
	local _Property = {
    }
    
    -- New    
    local _New = function(parent)
		local index = parent.__NodeNum or 0
		index = index + 1
		
		local frame = CreateFrame("Frame",nil,parent)
		frame.ID = index
		parent.__NodeNum = index
		parent.Height = parent.Height + nodeHeight
		
        frame:SetWidth(200)
        frame:SetHeight(nodeHeight)
		
		if index == 1 then
			frame:SetPoint("TOPRIGHT", parent, "TOPRIGHT", 0, - nodeHeight)
			frame:SetPoint("TOPLEFT", parent, "TOPLEFT", nodeIndent, - nodeHeight)
		else
			frame:SetPoint("TOPRIGHT", parent:GetChild("PropertySet"..(index-1)), "BOTTOMRIGHT", 0, 0)
			frame:SetPoint("TOPLEFT", parent:GetChild("PropertySet"..(index-1)), "BOTTOMLEFT", 0, 0)
		end
		
		frame:SetBackdrop(_FrameBackdrop)
		frame:SetBackdropColor(0,0,0,1)
		
		local title = CreateFrame("FontString","Title",frame,"OVERLAY","GameFontNormal")
		title:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, 0)
		title:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 0, 0)
		title:SetPoint("RIGHT", frame, "CENTER", -10, 0)
		
		local cbo = CreateFrame("ComboBox", "Set", frame)
		cbo:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, 0)
		cbo:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, 0)
		cbo:SetPoint("LEFT", title, "RIGHT", 0, 0)
		cbo.Editable = true
		cbo.AutoFocus = false
		
		cbo.OnValueChanged = Set_OnValueChanged
		cbo.OnEnterPressed = Set_OnEnterPressed
		cbo.OnEditFocusGained = Set_OnEditFocusGained
		cbo.OnEditFocusLost = Set_OnEditFocusLost

        return frame
    end
	
    local _WidgetInfo = {
        ["WidgetName"] = _WidgetName,
        ["Base"] = _Base,
        ["FuncProxy"] = _FuncProxy,
        ["Property"] = _Property,
        ["ScriptType"] = _ScriptType,
        ["New"] = _New,
    }
    
    _Widget[_WidgetName] = IGAS:NewWidget(_WidgetInfo)
end